package ru.spb.osll.myfit.server.execute;

import java.util.Date;

import fit.Fixture;
import fit.FixtureLoader;
import fit.Parse;
import fit.SemaphoreFixture;

import ru.spb.osll.myfit.server.execute.ProgressFixtureListener;

public class MyFitFixtureRunner extends Fixture {
	private FixtureLoader m_fixtureLoader;
	private ProgressFixtureListener m_progressFixtureListener;

	public MyFitFixtureRunner(FixtureLoader fixtureLoader,
			ProgressFixtureListener progressFixtureListener) {
		m_fixtureLoader = fixtureLoader;
		m_progressFixtureListener = progressFixtureListener;
		this.listener = progressFixtureListener;
	}

	@Override
	protected Fixture getLinkedFixtureWithArgs(Parse tables) throws Throwable {
		Parse header = tables.at(0, 0, 0);
		Fixture fixture = myfitLoadFixture(header.text());
		fixture.counts = counts;
		fixture.summary = summary;
		fixture.getArgsForTable(tables);
		return fixture;
	}

	public void doTables(Parse tables) {
		m_progressFixtureListener.countTotalTablesQuantity(tables);
		summary.put("run date", new Date());
		summary.put("run elapsed time", new RunTime());
		if (tables != null) {
			Parse heading = tables.at(0, 0, 0);
			if (heading != null) {
				try {
					Fixture fixture = getLinkedFixtureWithArgs(tables);
					fixture.listener = listener;
					interpretTables(tables, fixture);
				} catch (Throwable e) {
					exception(heading, e);
					interpretFollowingTables(tables);
				}
			}
		}

		listener.tablesFinished(counts);
		ClearSymbols();
		SemaphoreFixture.ClearSemaphores(); // Semaphores: clear all at end
	}

	protected void interpretTables(Parse tables, Fixture fixture) {
		try {
			fixture.getArgsForTable(tables);
			fixture.doTable(tables);
		} catch (Exception ex) {
			fixture.exception(tables.at(0, 0, 0), ex);
			fixture.listener.tableFinished(tables);
			return;
		}
		interpretFollowingTables(tables);
	}

	private void interpretFollowingTables(Parse tables) {
		listener.tableFinished(tables);
		tables = tables.more;
		while (tables != null) {
			Parse heading = tables.at(0, 0, 0);

			if (heading != null) {
				try {
					Fixture fixture = getLinkedFixtureWithArgs(tables);
					fixture.doTable(tables);
				} catch (Throwable e) {
					exception(heading, e);
				}
			}

			m_progressFixtureListener.tableFinished(tables);
			m_progressFixtureListener.setCounts(counts);
			m_progressFixtureListener.tablesFinished(counts);
			tables = tables.more;
		}
	}

	protected Fixture myfitLoadFixture(String fixtureName) throws Throwable {
		return m_fixtureLoader.disgraceThenLoad(fixtureName);
	}
}
